/*
 * Buffer aware TTA decoder
 * christophe.paris <at> free.fr
 *
 * Based on ttacodec.h from foobar-tta-plugin
 *
 * Description:	 TTAv1 decoder for Sony PSP
 * Developed by: Alexander Djourik <sasha@iszf.irk.ru>
 *               Pavel Zhilin <pzh@iszf.irk.ru>
 *		 cooleyes <eyes.cooleyes@gmail.com>
 *
 * Copyright (c) 1999-2004 Alexander Djourik. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * aint with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Please see the file COPYING in this directory for full copyright
 * information.
 */

#ifndef TTACODEC_H
#define TTACODEC_H

#define TTA_COPYRIGHT		"Copyright (c) 2004 Alexander Djourik. All rights reserved."

#define TTA_MYNAME			"ttaenc"
#define TTA_VERSION			"3.0"
#define TTA_BUILD			"20040404"

#define TTA_MAX_BPS			32
#define TTA_FRAME_TIME		1.04489795918367346939

#define TTA1_SIGN		0x31415454

#define TTA_MAX_ORDER		16

#define TTA_BLOCKS_PER_LOOP     1152

#ifdef _WIN32
#define __ATTRIBUTE_PACKED__
typedef unsigned __int64 uint64;
#else
#define __ATTRIBUTE_PACKED__	__attribute__((packed))
typedef unsigned long long uint64;
#endif


typedef struct {
	unsigned long k0;
	unsigned long k1;
	unsigned long sum0;
	unsigned long sum1;
} TTA_adapt;

typedef struct {
	long shift;
	long round;
	long error;
	long mutex;
	long qm[TTA_MAX_ORDER];
	long dx[TTA_MAX_ORDER];
	long dl[TTA_MAX_ORDER];
} TTA_fltst;

typedef struct {
	TTA_fltst fst;
	TTA_adapt rice;
	long last;
} TTA_channel_codec;

typedef struct {
	unsigned long bit_count;
	unsigned long bit_cache;
	unsigned char *bitpos;
	unsigned long crc32;
	unsigned long size;
	
	unsigned char *bit_buffer;
	unsigned char *BIT_BUFFER_END;
} TTA_bit_buffer;

typedef struct {
	TTA_channel_codec* enc;   // Encoders (1 per channel)
	TTA_channel_codec* tta;   // Always the first channel encoder
	TTA_bit_buffer *fbuf;     // Bit buffer containing 1 frame max
	long* data;
	unsigned long data_len;

	// Constant data during encoding
	unsigned long framelen;
	unsigned long srate;
	unsigned short num_chan;
	unsigned short bps;
	unsigned long blocks_per_loop;
	unsigned long byte_size;
	unsigned long is_float;
	unsigned short wavformat;
	unsigned short codec_num_chan;

} TTA_codec;


#ifdef _WIN32
#pragma pack(push,1)
#endif

typedef struct {
    unsigned long TTAid;
    unsigned short AudioFormat;
    unsigned short NumChannels;
    unsigned short BitsPerSample;
    unsigned long SampleRate;
    unsigned long DataLength;
    unsigned long CRC32;
} __ATTRIBUTE_PACKED__ TTA_header;

typedef struct {
    unsigned char id[3];
    unsigned short version;
    unsigned char flags;
    unsigned char size[4];
} __ATTRIBUTE_PACKED__ TTA_id3v2_header;

typedef struct _tag_TTA_io_callback {
	int (*read)(struct _tag_TTA_io_callback *io, void* buff, int size);
	int (*seek)(struct _tag_TTA_io_callback *io, int offset, int origin);
} __ATTRIBUTE_PACKED__ TTA_io_callback;

typedef struct {
	int ioHandle;
	TTA_id3v2_header id3v2;
	TTA_header TTAHeader;
	unsigned long ID3v2Len;

	unsigned long FrameTotal;
	unsigned long FrameLen;
	unsigned long LastFrameLen;
	unsigned long DataOffset;

	unsigned long* SeekTable;
	unsigned long* SeekOffsetTable;

	unsigned long FrameIndex;
	unsigned long MaxFrameLenBytes;
} __ATTRIBUTE_PACKED__ TTA_parser;

#ifdef _WIN32
#pragma pack(pop)
#endif

// ----------------------------------------------------------------------------

#ifdef __cplusplus
extern "C" {
#endif

// ----------------------------------------------------------------------------

TTA_codec* tta_codec_decoder_new(long srate, short num_chan, short bps, long blocks_per_loop);

void tta_codec_free(TTA_codec* ttaenc);


void bit_buffer_init_read(TTA_bit_buffer* bbuf);
										   
unsigned long tta_codec_decoder_decode_frame(TTA_codec* ttadec,
										   void *src,
										   unsigned long len,
										   void *dst);

void tta_codec_fill_header(TTA_codec* ttacodec,
						   TTA_header *hdr,
						   unsigned long data_len);

// ----------------------------------------------------------------------------

unsigned long tta_codec_get_frame_len(long srate);

// ----------------------------------------------------------------------------

TTA_parser* tta_parser_new(const char* filename);

unsigned char* tta_parser_read_frame(TTA_parser* ttaparser,
									unsigned long* FrameIndex,
									unsigned long* FrameLen,
									unsigned long* FrameLenBytes);

void tta_parser_seek(TTA_parser* ttaparser, uint64 seek_pos_100ns);

int tta_parser_eof(TTA_parser* ttaparser);

void tta_parser_free(TTA_parser** ttaparser);

// ----------------------------------------------------------------------------

unsigned long tta_crc32 (unsigned char *buffer, unsigned long len);

#ifdef __cplusplus
}
#endif	

// ----------------------------------------------------------------------------

#endif	/* TTACODEC_H */
